package redis

import (
	"encoding/json"
	"fmt"
	"github.com/cn-ygf/go-admin/pkg/config"
	"github.com/gomodule/redigo/redis"
)

var (
	pool *redis.Pool
)

func Load() error {
	var err error
	opts := make([]redis.DialOption, 0)
	pass := config.GetString("redis.pass")
	if pass != "" {
		opts = append(opts, redis.DialPassword(pass))
	}

	db := config.GetInt("redis.db")
	opts = append(opts, redis.DialDatabase(db))

	pool = &redis.Pool{
		Dial: func() (redis.Conn, error) {
			conn, err := redis.Dial("tcp", fmt.Sprintf("%s:%d", config.GetString("redis.host"), config.GetInt("redis.port")), opts...)
			if err != nil {
				fmt.Println(err.Error())
				return nil, err
			}
			return conn, nil
		},
		DialContext:     nil,
		TestOnBorrow:    nil,
		MaxIdle:         16,
		MaxActive:       32,
		IdleTimeout:     0,
		Wait:            false,
		MaxConnLifetime: 0,
	}

	return err
}

func Close() error {
	return pool.Close()
}

func GetString(key string) (string, error) {
	conn := pool.Get()
	defer conn.Close()
	return redis.String(conn.Do("get", key))
}

func GetInt(key string) (int, error) {
	conn := pool.Get()
	defer conn.Close()
	return redis.Int(conn.Do("get", key))
}

func GetInt64(key string) (int64, error) {
	conn := pool.Get()
	defer conn.Close()
	return redis.Int64(conn.Do("get", key))
}

func GetFloat64(key string) (float64, error) {
	conn := pool.Get()
	defer conn.Close()
	return redis.Float64(conn.Do("get", key))
}

func GetBytes(key string) ([]byte, error) {
	conn := pool.Get()
	defer conn.Close()
	return redis.Bytes(conn.Do("get", key))
}

func GetBool(key string) (bool, error) {
	conn := pool.Get()
	defer conn.Close()
	return redis.Bool(conn.Do("get", key))
}

func Keys(key string) ([]string, error) {
	conn := pool.Get()
	defer conn.Close()
	return redis.Strings(conn.Do("keys", key))
}

func BatDel(key string) error {
	conn := pool.Get()
	defer conn.Close()
	keys, err := redis.Strings(conn.Do("keys", key))
	if err != nil {
		return err
	}
	for _, item := range keys {
		_, err = conn.Do("del", item)
		if err != nil {
			return err
		}
	}
	return nil
}

func Set(key string, value any) error {
	conn := pool.Get()
	defer conn.Close()
	_, err := conn.Do("set", key, value)
	return err
}

func Del(key string) error {
	conn := pool.Get()
	defer conn.Close()
	_, err := conn.Do("del", key)
	return err
}

func SetJson(key string, value any) error {
	conn := pool.Get()
	defer conn.Close()
	buf, err := json.Marshal(value)
	if err != nil {
		return err
	}
	_, err = conn.Do("set", key, buf)
	return err
}

func LPushJson(key string, value any) error {
	conn := pool.Get()
	defer conn.Close()
	buf, err := json.Marshal(value)
	if err != nil {
		return err
	}
	_, err = conn.Do("lpush", key, buf)
	return err
}

func Brpop(key string, t int64) ([][]byte, error) {
	conn := pool.Get()
	defer conn.Close()
	return redis.ByteSlices(conn.Do("brpop", key, t))
}

func Do(commandName string, args ...interface{}) (reply interface{}, err error) {
	conn := pool.Get()
	defer conn.Close()
	return conn.Do(commandName, args...)
}

func Expire(key string, d int) error {
	conn := pool.Get()
	defer conn.Close()
	_, err := conn.Do("expire", key, d)
	return err
}
